#include "AbstractButton.h"
#include "Scene.h"

using namespace game_engine;
using namespace game_engine::gui;
using namespace game_engine::components;
using namespace game_engine::open_gl;
using namespace game_engine::utils;

///////////////////////////////////////////////////////////////////////////////
// Constructors and Destructors
///////////////////////////////////////////////////////////////////////////////

AbstractButton::AbstractButton(void)
    : Widget(), _checkable(false), _checked(false), _down(false), _simpleText()
{
}

AbstractButton::AbstractButton(Scene *scene, const string &name, const string &tag, 
                               const DrawLevelType drawLevel)
    : Widget(scene, name, tag, drawLevel), _checkable(false), _checked(false), 
    _down(false)
{
    _simpleText = new SimpleText(this, TIMES_ROMAN_10, ColorRGB::COLOR_WHITE);
    addComponent(_simpleText);
}

AbstractButton::~AbstractButton(void)
{
}

///////////////////////////////////////////////////////////////////////////////
// Other public methods
///////////////////////////////////////////////////////////////////////////////

boost::signals2::connection AbstractButton::connect(
    AbstractButton::signal_void_void_t &publisher, 
    const AbstractButton::signal_void_void_t::slot_type &subscriber)
{
    return publisher.connect(subscriber);
}

boost::signals2::connection AbstractButton::connect(
    AbstractButton::signal_void_bool_t &publisher, 
    const AbstractButton::signal_void_bool_t::slot_type &subscriber)
{
    return publisher.connect(subscriber);
}

void AbstractButton::update(const FLOAT32 time)
{
    Point pos;

    // First, check if button is enabled or visible
    if (!isVisible())
    {
        return;
    }
    else if (!isEnabled())
    {
        setTextColor(ColorRGB::COLOR_GREY);
        return;
    }

    // Check if left mouse button has been released over the button
    if (scene->isButtonUp(GLUT_LEFT_BUTTON, pos))
    {
        if (isMouseOver(pos) && isDown())
        {
            // Update button state
            if (isCheckable())
            {
                setChecked(!isChecked());
            }
            setDown(false);
            setTextColor(ColorRGB::COLOR_GREEN);
            //setFocus(true);

            // Emit signals
            _signalReleased();
            _signalClicked(true);
            if (isCheckable())
            {
                _signalToggled(isChecked());
            }
        }  // if (isMouseOver(pos) && isDown())

        else if (!isMouseOver(pos) && isDown())
        {
            // Update button state
            setDown(false);
            setTextColor(ColorRGB::COLOR_WHITE);
            //setFocus(true);

            // Emit signals
            _signalReleased();
        }
    }  // if (scene->isButtonUp(GLUT_LEFT_BUTTON, pos))

    // Check if left mouse button has been pressed over the button
    else if (scene->isButtonDown(GLUT_LEFT_BUTTON, pos))
    {
        if (isMouseOver(pos))
        {
            // Update button state
            setDown(true);
            setTextColor(ColorRGB::COLOR_BLUE);
            //setFocus(true);

            // Emit signal
            _signalPressed();
        }
    }
}

///////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////

const BOOL AbstractButton::isCheckable(void) const
{
    return _checkable;
}

const BOOL AbstractButton::isChecked(void) const
{
    return _checked;
}

const BOOL AbstractButton::isDown(void) const
{
    return _down;
}

AbstractButton::signal_void_bool_t& AbstractButton::signalClicked(void)
{
    return _signalClicked;
}

AbstractButton::signal_void_void_t& AbstractButton::signalPressed(void)
{
    return _signalPressed;
}

AbstractButton::signal_void_void_t& AbstractButton::signalReleased(void)
{
    return _signalReleased;
}

AbstractButton::signal_void_bool_t& AbstractButton::signalToggled(void)
{
    return _signalToggled;
}

const string& AbstractButton::text(void) const
{
    return _simpleText->getText();
}

///////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////

void AbstractButton::setCheckable(const BOOL checkable)
{
    _checkable = checkable;
}

void AbstractButton::setChecked(const BOOL checked)
{
    _checked = checked;
    _signalToggled(checked);
}

void AbstractButton::setDown(const BOOL down)
{
    _down = down;
}

void AbstractButton::setEnabled(const BOOL enabled)
{
    Widget::setEnabled(enabled);

    // Change text color
    if (enabled)
    {
        // FIXME : change this by a default active color
        _simpleText->setColor(ColorRGB::COLOR_WHITE);
    }
    else
    {
        _simpleText->setColor(ColorRGB::COLOR_GREY);
    }
}

void AbstractButton::setFocus(const BOOL focus)
{
    Widget::setFocus(focus);

    // Change text color
    if (focus)
    {
        _simpleText->setColor(ColorRGB::COLOR_GREEN);
    }
    else
    {
        _simpleText->setColor(ColorRGB::COLOR_WHITE);
    }
}

void AbstractButton::setFont(const FontType font)
{
    _simpleText->setFontType(font);
}

void AbstractButton::setText(const string& text)
{
    _simpleText->setText(text);
}

void AbstractButton::setTextColor(const ColorRGB &color)
{
    _simpleText->setColor(color);
}
